package com.gk.javaservice.util.rest;

import org.apache.http.HttpEntity;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.SecureRandom;
import java.util.Map;
import java.util.Map.Entry;


import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;

/**
 * http 工具封装类
 */
public class HttpURLConnectionUtils {

    private static HttpURLConnection conn;

    /**
     * 发送get请求
     *
     * @param url
     * @param headers
     * @return
     */
    public static String get(String url, Map<String, String> headers, Map<String, String> params) {

        String result = "";
        try {
            if(params!=null) {
                StringBuilder sbParams = new StringBuilder();
                for (Entry<String, String> entry : params.entrySet()) {
                    sbParams.append(entry.getKey());
                    sbParams.append("=");
                    sbParams.append(entry.getValue());
                    sbParams.append("&");
                }

                if (sbParams.length() > 0) {
                    sbParams.deleteCharAt(sbParams.lastIndexOf("&"));
                    if (url.indexOf("?") > 0) {
                        url = url + "&" + sbParams.toString();
                    } else {
                        url = url + "?" + sbParams.toString();
                    }
                }
            }

            URL restServiceURL = new URL(url);
            HttpURLConnection httpConnection = (HttpURLConnection) restServiceURL.openConnection();
            httpConnection.setRequestMethod("GET");
            httpConnection.setRequestProperty("Charsert", "UTF-8"); //设置请求编码
            httpConnection.setRequestProperty("Accept", "*/*");

            if (headers != null) {
                for (Entry<String, String> entry : headers.entrySet()) {
                    httpConnection.setRequestProperty(entry.getKey(), entry.getValue().toString());
                }
            }

            if (httpConnection.getResponseCode() != 200) {
                throw new RuntimeException("HTTP GET Request Failed with Error code : "
                        + httpConnection.getResponseCode() + " url:" + url);
            }

            InputStream inputStream = httpConnection.getInputStream();
            result = readAll(inputStream);
            inputStream.close();


        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }


    /**
     * 发送post form请求
     *
     * @param url
     * @param headers
     * @param params
     * @return
     */
    public static String postForm(String url, Map<String, String> headers, Map<String, String> params) {

        String result = "";

        try {
            StringBuilder sbParams = new StringBuilder();
            for (Entry<String, String> entry : params.entrySet()) {
                sbParams.append(entry.getKey());
                sbParams.append("=");
                sbParams.append(entry.getValue().toString());
                sbParams.append("&");
            }
            if (sbParams.length() > 0) {
                sbParams.deleteCharAt(sbParams.lastIndexOf("&"));
            }
//            if(sbParams.length()>99){
//                sbParams.appendCodePoint(postForm(""));
//                saveFileDown();
//
//            }

            URL reqUrl = new URL(url);
            conn = (HttpURLConnection) reqUrl.openConnection();

            //设置参数
            conn.setDoOutput(true);        //需要输出
            conn.setDoInput(true);        //需要输入
            conn.setUseCaches(false);    //不允许缓存
            conn.setRequestMethod("POST");        //设置POST方式连接

            //设置请求属性
           // httpConn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            //httpConn.setRequestProperty("Connection", "Keep-Alive");// 维持长连接
            conn.setRequestProperty("Charset", "UTF-8");
            conn.setRequestProperty("accept", "*/*");

            if (headers != null) {
                for (Entry<String, String> entry : headers.entrySet()) {
                    conn.setRequestProperty(entry.getKey(), entry.getValue().toString());
                }
            }

            //建立输入流，向指向的URL传入参数
            DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
            //dos.writeBytes(sbParams.toString()); 这个方法会有中文乱码
            dos.write(sbParams.toString().getBytes("utf-8")); //解决中文乱码
            dos.flush();
            dos.close();

//            if (httpConn.getResponseCode() != 200) {
//                throw new RuntimeException("HTTP POST form Request Failed with Error code : "
//                        + httpConn.getResponseCode() + " url:" + url + " form:" + params.toString());
//            }
//            InputStream inputStream = httpConn.getInputStream();
//            result = readAll(inputStream);
//            inputStream.close();

            BufferedReader bReader = new BufferedReader(new InputStreamReader(conn.getInputStream(),"UTF-8"));

            String line="";

            while(null != (line=bReader.readLine()))
            {
                result +=line;
            }
            bReader.close();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }

        return result;
    }


    public static void main(String[] args) throws IOException {
        String url="http://192.168.10.161:888/chfs/shared/2021-11-30/videos/20211130083508.mp4";
        url="http://192.168.10.106:888/chfs/shared/2021-12-02/videos/20211202172333_2.mp4";
        new HttpURLConnectionUtils().saveFileDown(url,"E:\\server\\datas\\GK480490","20211130083508.mp4","");

    }


    /**
     * @功能 远程文件下载
     * @param filePath 文件将要保存的目录
     * @param method 请求方法，包括POST和GET
     * @param url 请求的路径
     * @return
     */

    public static Boolean saveFileDown(String url, String filePath,String fileName, String method){
        // System.out.println("IN TO saveFileDown fileName---->"+filePath);
        //创建不同的文件夹目录
        File file=new File(filePath);
        //判断文件夹是否存在
        if (!file.exists())
        {
            //如果文件夹不存在，则创建新的的文件夹
            //http://192.168.80.170/live?app=myapp&stream=10
            file.mkdirs();
        }
        FileOutputStream fileOut = null;
        // HttpURLConnection conn = null;
        InputStream inputStream = null;
        try
        {


            //获取网络输入流
            inputStream=getStreamDownloadOutFile(url);
            BufferedInputStream bis = new BufferedInputStream(inputStream);
            //判断文件的保存路径后面是否以/结尾
            if (!filePath.endsWith("/")) {
                filePath += "/";
            }
            //写入到文件（注意文件保存路径的后面一定要加上文件的名称）
            fileOut = new FileOutputStream(filePath+fileName);
            BufferedOutputStream bos = new BufferedOutputStream(fileOut);
            byte[] buf = new byte[4096];
            int length = bis.read(buf);
            int max=length;
            //保存文件
            while(length != -1)
            {
                bos.write(buf, 0, length);
                length = bis.read(buf);
                //// System.out.println("完成度： " + length);
            }
            bos.close();
            bis.close();
             // System.out.println("下载完成！" );
            return true;
        } catch (Exception e)
        {
            e.printStackTrace();
            // System.out.println("抛出异常！！");
            return false;
        }


    }


    public static Boolean saveFileDownNoSSL(String urlStr, String filePath, String fileName, String method) {
        File file = new File(filePath);
        if (!file.exists()) {
            file.mkdirs();
        }

        try {
            // 忽略SSL验证，仅用于测试环境
            ignoreSsl();

            // 为当前连接创建不验证SSL的上下文，避免影响全局设置
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, getInsecureTrustManager(), new SecureRandom());
            HttpURLConnection connection = setupConnection(urlStr, sc, method);

            InputStream inputStream = connection.getInputStream();


            URL url = new URL(urlStr);
//            HttpURLConnection connection;
            if (url.getProtocol().toLowerCase().equals("https")) {
                connection = (HttpsURLConnection) url.openConnection();
            } else {
                connection = (HttpURLConnection) url.openConnection();
            }
            connection.setRequestMethod(method);
            connection.setConnectTimeout(5000);
            connection.setReadTimeout(5000);

//            InputStream inputStream = connection.getInputStream();
            BufferedInputStream bis = new BufferedInputStream(inputStream);

            if (!filePath.endsWith("/")) {
                filePath += "/";
            }
            FileOutputStream fileOut = new FileOutputStream(filePath + fileName);
            BufferedOutputStream bos = new BufferedOutputStream(fileOut);
            byte[] buf = new byte[4096];
            int length;
            while ((length = bis.read(buf)) != -1) {
                bos.write(buf, 0, length);
            }
            bos.close();
            bis.close();
            return true;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            throw new RuntimeException("Error setting up SSL context", e);
        }
    }

    private static void ignoreSsl() throws NoSuchAlgorithmException, KeyManagementException {
        // 忽略SSL证书验证，不建议在生产环境中使用
        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
            public void checkClientTrusted(X509Certificate[] certs, String authType) {}
            public void checkServerTrusted(X509Certificate[] certs, String authType) {}
        }};

        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, trustAllCerts, new java.security.SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    }

    private static TrustManager[] getInsecureTrustManager() {
        return new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                    public void checkClientTrusted(X509Certificate[] certs, String authType) {}
                    public void checkServerTrusted(X509Certificate[] certs, String authType) {}
                }
        };
    }

    private static HttpURLConnection setupConnection(String urlStr, SSLContext sc, String method) throws IOException {
        URL url = new URL(urlStr);
        HttpURLConnection connection;
        if ("https".equalsIgnoreCase(url.getProtocol())) {
            HttpsURLConnection httpsConnection = (HttpsURLConnection) url.openConnection();
            httpsConnection.setSSLSocketFactory(sc.getSocketFactory());
            connection = httpsConnection;
        } else {
            connection = (HttpURLConnection) url.openConnection();
        }
        connection.setRequestMethod(method);
        connection.setConnectTimeout(5000);
        connection.setReadTimeout(5000);
        return connection;
    }

    /**
     * 下载文件，返回输入流。
     *
     * @param apiUrl api接口
     * @return (文件)输入流
     * @throws Exception
     */
    public static InputStream getStreamDownloadOutFile(String apiUrl) throws Exception {
        // System.out.println("IN TO getStreamDownloadOutFile ---->"+apiUrl);
        InputStream is = null;
        CloseableHttpClient httpClient = HttpClients.createDefault(); //创建默认http客户端
        RequestConfig requestConfig = RequestConfig.DEFAULT; //采用默认请求配置
        HttpGet request = new HttpGet(apiUrl); //通过get方法下载文件流
        request.setConfig(requestConfig); //设置请头求配置
        try {
            CloseableHttpResponse httpResponse = httpClient.execute(request); //执行请求，接收返回信息
            int statusCode = httpResponse.getStatusLine().getStatusCode(); //获取执行状态
            if (statusCode != HttpStatus.SC_OK && statusCode != HttpStatus.SC_CREATED) {
                request.abort();
            } else {
                HttpEntity entity = httpResponse.getEntity();
                if (null != entity) {
                    is = entity.getContent(); //获取返回内容
                }
            }
        } catch (Exception e) {
            // System.out.println("异常："+e.toString());
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            e.printStackTrace(new PrintStream(baos));
            String exception = baos.toString();
            // System.out.println("baos:" + exception);
            e.printStackTrace();
            request.abort();
        }
        return is;
    }


    /**
     * 发送json请求
     *
     * @param url
     * @param headers
     * @param jsonData
     * @return
     */
    public static String postJSON(String url, Map<String, Object> headers, String jsonData) {

        String result = "";

        try {

            URL reqUrl = new URL(url);
            HttpURLConnection httpConn = (HttpURLConnection) reqUrl.openConnection();

            //设置参数
            httpConn.setDoOutput(true);        //需要输出
            httpConn.setDoInput(true);        //需要输入
            httpConn.setUseCaches(false);    //不允许缓存
            httpConn.setRequestMethod("POST");        //设置POST方式连接

            //设置请求属性
            httpConn.setRequestProperty("Content-Type", "application/json");
            httpConn.setRequestProperty("Connection", "Keep-Alive");// 维持长连接
            httpConn.setRequestProperty("Charset", "UTF-8");
            httpConn.setRequestProperty("accept", "*/*");

            if (headers != null) {
                for (Entry<String, Object> entry : headers.entrySet()) {
                    httpConn.setRequestProperty(entry.getKey(), entry.getValue().toString());
                }
            }

            //建立输入流，向指向的URL传入参数
            DataOutputStream dos = new DataOutputStream(httpConn.getOutputStream());
            //dos.writeBytes(jsonData); 这个方法会有中文乱码,使用下面的方法解决
            dos.write(jsonData.getBytes("utf-8"));
            dos.flush();
            dos.close();

            if (httpConn.getResponseCode() != 200) {
                throw new RuntimeException("HTTP POST json Request Failed with Error code : "
                        + httpConn.getResponseCode() + " url:" + url + " json:" + jsonData);
            }

            InputStream inputStream = httpConn.getInputStream();
            result = readAll(inputStream);
            inputStream.close();

        } catch (Exception e) {
            e.printStackTrace();
        }

        return result;
    }


    /**
     * 读取字节流
     *
     * @param inputStream
     * @return
     */
    private static String readAll(InputStream inputStream) {

        StringBuilder builder = new StringBuilder();

        try {
            byte[] b = new byte[1024];
            int length = -1;
            // System.out.println("=========================================================");
            while ((length = inputStream.read(b)) != -1) {
                // // System.out.println(b);
                builder.append(new String(b, 0, length,"UTF-8"));
                // System.out.println(builder.toString());
            }
            // System.out.println("=========================================================");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return builder.toString();
    }


}
